package com.caocaog.market.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.caocaog.market.entity.*;
import com.caocaog.market.finance.entity.MkBillBase;
import com.caocaog.market.finance.service.FinanceLineService;
import com.caocaog.market.finance.service.MkBillBaseService;
import com.caocaog.market.mapper.OrderRefundMapper;
import com.caocaog.market.pay.UnionPay;
import com.caocaog.market.pay.syb.dto.SybDto;
import com.caocaog.market.pay.syb.utils.SybPay;
import com.caocaog.market.pay.wxpay.WxPay;
import com.caocaog.market.service.*;
import com.caocaog.market.vo.MemberPointModifyVO;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.exception.CheckFailedException;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Optional;

/**
 * 订单退款信息
 *
 * @author jeecg-boot
 * @date 2021-12-01
 */
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, OrderRefund> implements IOrderRefundService {
    @Autowired
    private IOrderPayService orderPayService;
    @Autowired
    private IOrderStatusInfoService orderStatusInfoService;
    @Autowired
    private IOrderBaseService orderBaseService;
    @Autowired
    private MkBillBaseService billBaseService;
    @Autowired
    private UnionPay unionPay;
    @Autowired
    private MemberService memberService;
    @Setter(onMethod_ = @Autowired)
    private FinanceLineService financeLineService;
    @Resource
    private IMemberPointStatementService memberPointStatementService;

    @Resource
    private SybPay sybPay;
    @Resource
    private WxPay wxPay;

    public Result editSyb(OrderRefund orderRefund, String loginName) {
        OrderRefund check = super.baseMapper.selectById(orderRefund.getId());
        if (check.getAudit() == 1) {
            return Result.error("请勿重复审核哟~");
        }
        String orderNo = orderRefund.getOrderNo();
        if (orderRefund.getAudit() == 1 && !orderRefund.getAudit().equals(check.getAudit())) {
//			审核通过
            log.info("orderRefund审核通过" + orderRefund.getId());
            //添加状态记录
            OrderStatusInfo orderStatusInfo = OrderStatusInfo.builder().orderId(orderRefund.getOrderId())
                    .orderNo(orderNo).orderStatusName("商家同意退款").createBy(loginName)
                    .createTime(new Date()).remark("").build();
            orderStatusInfoService.save(orderStatusInfo);
            OrderPay orderPay = orderPayService.getOne(new QueryWrapper<OrderPay>().eq("order_id", orderRefund.getOrderId()));
            SybDto sybDto = new SybDto();
            //通联金额单位转换为分
            BigDecimal amount = new BigDecimal(orderPay.getPayAmount());
            amount = amount.movePointRight(2);
            sybDto.setTrxAmt(amount.longValue());
            sybDto.setReqSn(orderNo);
            sybDto.setOldReqSn(orderNo);
            sybDto.setOldTrxId(orderPay.getPaySerno());
            sybDto.setRemark("商家同意退款");
            try {
                sybPay.refund(sybDto);
                orderRefund.setPayStatus(1);//退款成功
                orderRefund.setPayRefundSerno(orderPay.getPaySerno());
                OrderBase orderBase = orderBaseService.getById(orderRefund.getOrderId());
                orderBase.setStatus("-3");
                log.info("更新订单状态");
                orderBaseService.updateById(orderBase);
                //更新结算状态 4已退款
                MkBillBase mkBillBase = billBaseService.findBillIsExist(orderBase.getOrderNo());
                if (oConvertUtils.isNotEmpty(mkBillBase)) {
                    billBaseService.updatePayStatusAndInsertHistory(orderBase.getOrderNo(), 4);
                }
                financeLineService.deleteFinanceLineByOrderId(orderBase.getId());
            } catch (Exception e) {
                log.error("通联退款异常:", e);
                return Result.error("退款异常");
            }
        } else if (orderRefund.getAudit() == 2 && !orderRefund.getAudit().equals(check.getAudit())) {
            log.info("orderRefund审核不通过" + orderRefund.getId());
            //回滚 订单状态
            OrderBase orderBase = orderBaseService.getById(orderRefund.getOrderId());
            orderBase.setStatus(orderRefund.getOrderStatus());
            orderBaseService.updateById(orderBase);
            //添加状态记录
            OrderStatusInfo orderStatusInfo = OrderStatusInfo.builder().orderId(orderRefund.getOrderId())
                    .orderNo(orderNo).orderStatusName("商家拒绝退款").createBy(loginName)
                    .createTime(new Date()).remark("").build();
            orderStatusInfoService.save(orderStatusInfo);
        }
        super.baseMapper.updateById(orderRefund);
        return Result.OK("操作成功", orderRefund);
    }

    /**
     * 微信退款
     *
     * @param orderRefund 订单退款类
     * @param loginName   登录人
     * @return 退款结果
     */
    @Override
    public Result edit(OrderRefund orderRefund, String loginName) {
        OrderRefund check = super.baseMapper.selectById(orderRefund.getId());
        if (check.getAudit() == 1) {
            return Result.error("请勿重复审核哟~");
        }

        if (orderRefund.getAudit() == 1) {
//			审核通过
            log.info("orderRefund审核通过" + orderRefund.getId());
            //添加状态记录
            OrderStatusInfo orderStatusInfo = OrderStatusInfo.builder().orderId(orderRefund.getOrderId())
                    .orderNo(orderRefund.getOrderNo()).orderStatusName("商家同意退款").createBy(loginName)
                    .createTime(new Date()).remark("").build();
            orderStatusInfoService.save(orderStatusInfo);
            OrderPay orderPay = orderPayService.getOne(new QueryWrapper<OrderPay>().eq("order_id", orderRefund.getOrderId()));
            unionPay.refund(orderRefund.getId(), orderPay.getPaySerno(), orderPay.getPayWay());
            // 退款成功之后这里吧订单的积分回滚一下
            OrderBase orderBase = Optional.ofNullable(orderBaseService.getById(orderRefund.getOrderId())).orElseThrow(() -> new JeecgBootException("无法根据订单ID获取到订单信息"));
            memberPointModifyOfOrderRefund(orderBase);
        } else if (orderRefund.getAudit() == 2 && !orderRefund.getAudit().equals(check.getAudit())) {
            log.info("orderRefund审核不通过" + orderRefund.getId());
            //回滚 订单状态
            OrderBase orderBase = orderBaseService.getById(orderRefund.getOrderId());
            orderBase.setStatus(orderRefund.getOrderStatus());
            orderBaseService.updateById(orderBase);
            //添加状态记录
            OrderStatusInfo orderStatusInfo = OrderStatusInfo.builder()
                    .orderId(orderRefund.getOrderId())
                    .orderNo(orderRefund.getOrderNo())
                    .orderStatusName("商家拒绝退款")
                    .createBy(loginName)
                    .createTime(new Date())
                    .remark("")
                    .build();
            orderStatusInfoService.save(orderStatusInfo);
        }
        super.baseMapper.updateById(orderRefund);
        return Result.OK("操作成功", orderRefund);
    }

    /**
     * 订单退款的积分变动回调方法
     *
     * @param orderBase 订单基础信息
     */
    public void memberPointModifyOfOrderRefund(OrderBase orderBase) {
        BigDecimal takePoint = orderBase.getTakePoint();
        if (takePoint == null || BigDecimal.ZERO.compareTo(takePoint) == 0) {
            log.info("订单 {} ，获得积分为0，积分无变动！", orderBase.getId());
            return;
        }
        MemberPointModifyVO memberPointModifyVO = new MemberPointModifyVO();
        memberPointModifyVO.setMemberId(orderBase.getMemberId()).setPoint(orderBase.getTakePoint().negate()).setModifyType(CacheConstant.POINT_MODIFY_TYPE_REFUND).setModifyMessage(String.format("订单退款成功，回退会员积分 id:{%s}。", orderBase.getId()));
        memberPointStatementService.modifyMemberPoint(memberPointModifyVO);
    }

    @Override
    public void forceOrderRefund(String orderNo, String refundCause, String name, Integer userType) {

        log.info("根据订单号获取订单信息");
        OrderBase orderBase = orderBaseService.getOne(new LambdaQueryWrapper<OrderBase>().eq(OrderBase::getOrderNo, orderNo));
        if (orderBase == null) throw new JeecgBootException("未查到订单实体, orderNo-> " + orderNo);

        log.info("获取或添加订单退款信息");
        OrderRefund orderRefund = this.getOrAdd(orderBase);

        log.info("根据订单id获取订单支付信息");
        OrderPay orderPay = orderPayService.getOne(new LambdaQueryWrapper<OrderPay>().eq(OrderPay::getOrderId, orderBase.getId()));

        log.info("申请退款");
        unionPay.refund(orderRefund.getId(), orderPay.getPaySerno(), orderPay.getPayWay());

        log.info("更新订单信息状态为'退款成功'");
        orderBase.setStatus("-3");
        orderBaseService.updateById(orderBase);

        // TODO delete
        log.info("更新账单记录为'已退款'");
        billBaseService.updatePayStatusAndInsertHistory(orderNo, 4);

        financeLineService.deleteFinanceLineByOrderId(orderBase.getId());

        log.info("添加状态记录");
        OrderStatusInfo orderStatusInfo = OrderStatusInfo.builder().orderId(orderBase.getId())
                .orderNo(orderBase.getOrderNo()).orderStatusName("商家已取消了您的订单").createBy(name)
                .createTime(new Date()).remark(refundCause).build();
        orderStatusInfoService.save(orderStatusInfo);
    }

    @Override
    public void forceOrderComplete(String orderNo, String completeCause, String name, Integer userType) {
        if (userType != 1) throw new CheckFailedException("无权限");

        log.info("根据订单id获取订单信息");
        OrderBase orderBase = orderBaseService.getOne(new LambdaQueryWrapper<OrderBase>().eq(OrderBase::getOrderNo, orderNo));
        if (orderBase == null) throw new JeecgBootException("未查到订单实体, orderNo-> " + orderNo);

        log.info("更新订单信息状态为'已完成'");
        orderBase.setStatus("3");
        orderBaseService.updateById(orderBase);

        log.info("更新账单记录为'待结算'");
        billBaseService.updatePayStatusAndInsertHistory(orderNo, 1);

        log.info("添加状态记录");
        OrderStatusInfo orderStatusInfo = OrderStatusInfo.builder().orderId(orderBase.getId())
                .orderNo(orderBase.getOrderNo()).orderStatusName("商家已完成了您的订单").createBy(name)
                .createTime(new Date()).remark(completeCause).build();
        orderStatusInfoService.save(orderStatusInfo);
    }

    private OrderRefund getOrAdd(OrderBase orderBase) {
        OrderRefund orderRefund = super.baseMapper.selectOne(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, orderBase.getId()));
        if (orderRefund != null && StringUtils.isNotBlank(orderRefund.getId())) {
            orderRefund.setAudit(1);//设置为审核通过
            super.baseMapper.updateById(orderRefund);
            return orderRefund;
        } else {
            orderRefund = new OrderRefund();
        }
        OrderPay orderPay = orderPayService.getOne(new QueryWrapper<OrderPay>().eq("order_id", orderBase.getId()));
        Member member = this.memberService.getBaseMapper().selectById(orderBase.getMemberId());
        if (member == null) member = new Member();
        orderRefund.setOpenid(member.getWxOpenid());
        orderRefund.setOrderNo(orderBase.getOrderNo());
        orderRefund.setAudit(1);//审核通过
        orderRefund.setPayStatus(0);//待退款
        orderRefund.setOrderStatus(orderBase.getStatus());
        orderRefund.setCreateBy(member.getUserName());
        orderRefund.setCreateTime(DateUtils.getDate());
        orderRefund.setRefundAmount(orderPay.getPayAmount());
        orderRefund.setOrderId(orderBase.getId());
        orderRefund.setMerchantId(orderBase.getMerchantId());
        orderRefund.setShopId(orderBase.getShopId());
        /*订单号规则 时间yyyymmddhhmmssSSS加手机号后四位加来源*/
        String phone = member.getMobile();
        if (phone == null) phone = "00000";
        else phone = phone.substring(phone.length() - 5);
        Date date = new Date();
        String timestamp = DateUtils.date2Str(date, DateUtils.yyyymmddhhmmssSSS.get());
        String refundNo = "T" + timestamp + phone + orderBase.getSource();
        orderRefund.setRefundNo(refundNo);
        /*orderBase.setStatus("-2");//申请售后
        this.orderBaseService.updateById(orderBase);*/
        super.baseMapper.insert(orderRefund);
        return orderRefund;
    }
}
